package cn.cj.erp.common.http;

import cn.cj.erp.common.constants.BizCodeEnum;
import lombok.extern.slf4j.Slf4j;
import java.io.Serializable;

/**
 * 返回数据
 * @author jianchene0
 */
@Slf4j
public class Result<T> {
    /** 响应码： 200成功 其他失败 */
    private int code;

    /** 响应信息 */
    private String msg;

    /** 响应体数据 */
    private T data;

    public Result() {
    }

    public Result(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public Result(int code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public int getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }

    public T getData() {
        return data;
    }

    public Result<T> setCode(int code) {
        this.code = code;
        return this;
    }

    public Result<T> setMsg(String msg) {
        this.msg = msg;
        return this;
    }

    public Result<T> setData(T data) {
        this.data = data;
        return this;
    }

    /**
     * 成功响应体
     * @param data 响应内容
     * @return Result
     */
    public static <T> Result<T> ok(T data) {
        return new Result<>(BizCodeEnum.OK.getCode(), BizCodeEnum.OK.getMsg(), data);
    }

    /**
     * 成功响应体
     * @return Result<T>
     */
    public static <T> Result<T> ok() {
        return new Result<>(BizCodeEnum.OK.getCode(), BizCodeEnum.OK.getMsg());
    }

    /**
     * 失败响应体
     * @return Result<T>
     */
    public static <T> Result<T> error() {
        return new Result<>(BizCodeEnum.FAIL.getCode(), BizCodeEnum.FAIL.getMsg());
    }

    /**
     * 失败响应体
     * @param bizCode {@link BizCodeEnum} 返回码枚举
     * @return Result<T>
     */
    public static <T> Result<T> error(BizCodeEnum bizCode) {
        return new Result<>(bizCode.getCode(), bizCode.getMsg());
    }

    /**
     * 失败响应体
     * @param result {@link Result} 操作结果
     * @return Result<T>
     */
    public static <T> Result<T> error(Result<?> result) {
        return new Result<>(result.getCode(), result.getMsg());
    }

    /**
     * 失败响应体
     * @param code 错误码
     * @param msg 错误描述
     * @return Result<T>
     */
    public static <T> Result<T> error(int code, String msg) {
        return new Result<>(code, msg);
    }

    /**
     * 失败响应体
     * @param msg 错误描述
     * @return Result<T>
     */
    public static<T> Result<T> error(String msg) {
        return new Result<>(BizCodeEnum.FAIL.getCode(), msg);
    }

    /**
     * 微服务降级
     * @return Result<T>
     */
    public static <T> Result<T> fallback() {
        return new Result<>(BizCodeEnum.SENTINEL_DEGRADE_ERROR.getCode(), BizCodeEnum.SENTINEL_DEGRADE_ERROR.getMsg());
    }

    /**
     * 成功响应体
     * @param data 响应内容
     * @return Result<T>
     */
    public static <T> Result<T> query(T data) {
        return new Result<>(BizCodeEnum.OK.getCode(), BizCodeEnum.OK.getMsg(), data);
    }

    /**
     * 保存响应处理
     * @param result 保存操作返回值
     * @return Result<T>d
     */
    public static <T> Result<T> save(Boolean result) {
        return result ? Result.ok() : Result.error(BizCodeEnum.FAIL_SAVE.getCode(), BizCodeEnum.FAIL_SAVE.getMsg());
    }

    /**
     * 更新响应处理
     * @param result 更新操作返回值
     * @return Result<T>
     */
    public static <T> Result<T> update(Boolean result) {
        return result ? Result.ok() : Result.error(BizCodeEnum.FAIL_UPDATE.getCode(), BizCodeEnum.FAIL_UPDATE.getMsg());
    }

    /**
     * 删除响应处理
     * @param result 删除操作返回值
     * @return Result<T>
     */
    public static <T> Result<T> remove(Boolean result) {
        return result ? Result.ok() : Result.error(BizCodeEnum.FAIL_DELETE.getCode(), BizCodeEnum.FAIL_DELETE.getMsg());
    }

    /**
     * 响应体是否成功
     * @return boolean
     */
    public boolean isOk() {
        return this.code == BizCodeEnum.OK.getCode();
    }

    /**
     * 响应体是否失败
     * @return boolean
     */
    public boolean isError() {
        return !isOk();
    }

    @Override
    public String toString() {
        return String.format("%s(code=%s, msg=%s, data=%s)", Result.class.getSimpleName(), this.code, this.msg, this.data);
    }
}
